package com.jidolstar.astro
{
	/**
	 * ALTimeConverter
	 * 
	 * Various static methods.
	 * "Astronomical Algorithms"(2nd Edition), by Jean Meeus
	 * 
	 * @author Yongho,Ji (jidolstar@gmail.com)
	 * @since 2009.04.03
	 */ 	
	public class ALTimeConverter {
		/**
		 * 현재 Julian Date(JD)
		 */ 
		static public function get currentJD():Number {
			var date:ALDate = new ALDate();
			return date.JD;
		}
		/**
		 * 현재 Julian Ephemeris Date(JDE)
		 */ 
		static public function get currentJDE():Number {
			var date:ALDate = new ALDate();
			var deltaT:Number = ALDynamicalTime.deltaT( date.fractionalYear );
			return date.JD + deltaT / 86400.0;
		}
		/**
		 * Julian Year
		 * @param fromJD
		 * @param toJD
		 * @return Julian Year
		 */ 
		static public function getJulianYear( fromJD:Number, toJD:Number ):Number {
			return (toJD - fromJD)/365.25;
		}
		/**
		 * Julian Year, between J2000.0 and the stating epoch.
		 * @param JD
		 * @return Julian Year
		 */ 		
		static public function getJulianYearJ2000( JD:Number ):Number {
			return (JD - ALConst.JD_J2000 ) / 365.25;
		}  
		/**
		 * Julian Century
		 * @param fromJD
		 * @param toJD
		 * @return Julian Century
		 */ 
		static public function getJulianCentury( fromJD:Number, toJD:Number ):Number {
			return (toJD - fromJD)/36525;
		}
		/**
		 * Julian Century, between J2000.0 and the starting epoch.  
		 * Let T be the time interval, in Julian centuries, between J2000.0 and the starting epoch. 
		 * @param JD
		 * @return Julian Century
		 */ 
		static public function getJulianCenturyJ2000( JD:Number ):Number {
			return ( JD - ALConst.JD_J2000 ) / 36525;
		}
		/**
		 * Conversion of Local Civil Time (LCT) to Julian Date(JD) 
		 * @param year 년 
		 * @param month 월
		 * @param frctionalDay 분수값을 가지는 일(day)
		 * @param timezoneOffset KST의 경우 -540 minutes( = -9 hours ), 경도 0도 부터 동쪽은 -, 서쪽은 +값이고 반드시 단위는 minute이어야 한다. 
		 */ 
		static public function LCT2JD( year:int, month:int, fractionalDay:Number, timezoneOffset:Number = -540 ):Number {
			//UT = KST - 9h
			var date:ALDate = new ALDate( year, month, fractionalDay + timezoneOffset / 1440 );
			return date.JD;
		}
		/**
		 * Conversion of Julian Date(JD) to Local Civil Time (지방시민시) 
		 * @param JD Julain Date
		 * @param timezoneOffset KST의 경우 -540 minutes( = -9 hours ), 경도 0도 부터 동쪽은 -, 서쪽은 +값이고 반드시 단위는 minute이어야 한다.
		 * @return ALCalendarDate 객체
		 */ 
		static public function JD2LCT( JD:Number, timezoneOffset:Number = -540 ):ALCalendarDate {
			//KST = UT + 9h
			var date:ALDate = new ALDate( JD - timezoneOffset / 1440 );
			return date.calendarDate
		}
		/**
		 * Conversion of Local Civil Time(LCT) to Greenwich Mean Sidereal Time(GMST)
		 * @param year 년 
		 * @param month 월
		 * @param frctionalDay 분수값을 가지는 일(day)
		 * @param timezoneOffset KST의 경우 -540 minutes( = -9 hours ), 경도 0도 부터 동쪽은 -, 서쪽은 +값이고 반드시 단위는 minute이어야 한다.
		 * @return  Greenwich Mean Sidereal Time(GMST) in radians
		 */ 
		static public function LCT2GMST( year:int, month:int, fractionalDay:Number, timezoneOffset:Number ):Number {
			var JD:Number = LCT2JD( year, month, fractionalDay, timezoneOffset );
			return JD2GMST( JD );
		}
		/**
		 * Conversion of Local Civil Time(LCT) to Greenwich Mean Sidereal Time(GAST)
		 * @param year 년 
		 * @param month 월
		 * @param frctionalDay 분수값을 가지는 일(day)
		 * @param timezoneOffset KST의 경우 -540 minutes( = -9 hours ), 경도 0도 부터 동쪽은 -, 서쪽은 +값이고 반드시 단위는 minute이어야 한다.
		 * @param nutationInLongitude the nutation in longitude in radian
		 * @param obliquityOfEcliptic the true obliquity of the ecliptic in radian
		 * @return  Greenwich Apparent Sidereal Time(GAST) in radians
		 */ 		
		static public function LCT2GAST( year:int, month:int, fractionalDay:Number, timezoneOffset:Number, nutationInLongitude:Number, obliquityOfEcliptic:Number ):Number {
			var JD:Number = LCT2JD( year, month, fractionalDay, timezoneOffset );
			return JD2GAST( JD, nutationInLongitude, obliquityOfEcliptic );
		}
		/**
		 * Conversion of Local Civil Time(LCT) to Local Mean Sidereal Time(LMST)
		 * @param year 년 
		 * @param month 월
		 * @param frctionalDay 분수값을 가지는 일(day)
		 * @param timezoneOffset KST의 경우 -540 minutes( = -9 hours ), 경도 0도 부터 동쪽은 -, 서쪽은 +값이고 반드시 단위는 minute이어야 한다.
		 * @param obsLongitude observer longitude in degrees, East is Positive
		 * @return  Greenwich Mean Sidereal Time(LMST) in radians
		 */ 
		static public function LCT2LMST( year:int, month:int, fractionalDay:Number, timezoneOffset:Number, obsLongitude:Number ):Number {
			var JD:Number = LCT2JD( year, month, fractionalDay, timezoneOffset );
			return JD2LMST( JD, obsLongitude );			
		}
		/**
		 * Conversion of Local Civil Time(LCT) to Local Apparent Sidereal Time(LAST)
		 * @param year 년 
		 * @param month 월
		 * @param frctionalDay 분수값을 가지는 일(day)
		 * @param timezoneOffset KST의 경우 -540 minutes( = -9 hours ), 경도 0도 부터 동쪽은 -, 서쪽은 +값이고 반드시 단위는 minute이어야 한다.
		 * @param obsLongitude observer longitude in degrees, East is Positive
		 * @param nutationInLongitude the nutation in longitude in radian
		 * @param obliquityOfEcliptic the true obliquity of the ecliptic in radian
		 * @return  Greenwich Apparent Sidereal Time(LAST) in radians
		 */ 
		static public function LCT2LAST( year:int, month:int, fractionalDay:Number, timezoneOffset:Number, obsLongitude:Number, nutationInLongitude:Number, obliquityOfEcliptic:Number  ):Number {
			var JD:Number = LCT2JD( year, month, fractionalDay, timezoneOffset );
			return JD2LAST( JD, obsLongitude, nutationInLongitude, obliquityOfEcliptic );			
		}		
		/**
		 * Conversion of Julian Date(JD) to Julian Ephemeris Date(JDE) 
		 * 
		 * @param JD Julian Date
		 * @return Julian Ephemeris Date(JDE) 
		 */ 
		static public function JD2JDE( JD:Number ):Number {
			var date:ALDate = new ALDate( JD );
			var deltaT:Number = ALDynamicalTime.deltaT( date.fractionalYear );
			return date.JD + deltaT / 86400.0;
		}
		/**
		 * Conversion of Julian Date(JD) to Greenwich Mean Sidereal Time(GMST)
		 * @param jd Julian Date
		 * @return GMST in radians
		 */ 
		static public function JD2GMST( JD:Number ):Number {
			var T:Number = (JD - 2451545.0) / 36525.0;
			var T2:Number = T * T;
			var GMST_degress:Number = 
							280.46061837 + 360.98564736629 * ( JD - 2451545.0 )  
							+ (0.000387933 - T / 38710000) * T2;
			return ALMath.mapTo0To2PIRange( GMST_degress * ALConst.D2R );
		} 
		/**
		 * Conversion of Julian Date(JD) to Local Mean Sidereal Time(GMST)
		 * @param jd Julian Date
		 * @param obsLongitude observer longitude in degrees, East is Positive
		 * @return LMST in radians
		 */ 
		static public function JD2LMST( JD:Number, obsLongitude:Number ):Number {
			var T:Number = (JD - 2451545.0) / 36525.0;
			var T2:Number = T * T;
			var GMST_degress:Number = 
							280.46061837 + 360.98564736629 * ( JD - 2451545.0 )  
							+ (0.000387933 - T / 38710000) * T2;
			var LMST_degrees:Number = GMST_degress + obsLongitude;
			return ALMath.mapTo0To2PIRange( LMST_degrees * ALConst.D2R );	
		}	
		/**
		 * Conversion of Julian Date(JD) to Greenwich Apparent Sidereal Time(GAST)<br><br>
		 * GAST = GMST + Δψ cos ε<br>
		 * Δψ: 황도상에서 장동운동에 의한 황경 변화값(the nutation in longitude)<br>
		 * Δε: 황도상에서 장동운동에 의한 기울기 변화값(the nutation in obliquity)<br>  
		 * ε0: 적도와 황도의 기울기 평균값(the mean obliquity of the ecliptic)<br>
		 * ε : 적도와 황도의 기울기 실제값(the true obliquity of the ecliptic) ε = ε0 + Δε<br>
		 * @param JD Julian Date
		 * @param nutationInLongitude the nutation in longitude in radian
		 * @param obliquityOfEcliptic the true obliquity of the ecliptic in radian
		 * @return Greenwich Apparent Sidereal Time(GAST) in radians
		 */ 
		static public function JD2GAST( JD:Number, nutationInLongitude:Number, obliquityOfEcliptic:Number ):Number {
			var GMST:Number = JD2GMST( JD );
			var correction:Number = nutationInLongitude * Math.cos( obliquityOfEcliptic );
			var GAST:Number = GMST + correction;
			return GAST;
		}
		/**
		 * Conversion of Julian Date(JD) to Local Apparent Sidereal Time(LAST)<br><br>
		 * GAST = GMST + Δψ cos ε<br>
		 * Δψ: 황도상에서 장동운동에 의한 황경 변화값(the nutation in longitude)<br>
		 * Δε: 황도상에서 장동운동에 의한 기울기 변화값(the nutation in obliquity)<br>  
		 * ε0: 적도와 황도의 기울기 평균값(the mean obliquity of the ecliptic)<br>
		 * ε : 적도와 황도의 기울기 실제값(the true obliquity of the ecliptic) ε = ε0 + Δε<br>
		 * 
		 * @param JD Julian Date
		 * @param obsLongitude observer longitude in degrees, East is Positive
		 * @param nutationInLongitude the nutation in longitude in radian
		 * @param obliquityOfEcliptic the true obliquity of the ecliptic in radian
		 * @return Local Apparent Sidereal Time(LAST) in radians
		 */		
		static public function JD2LAST( JD:Number, obsLongitude:Number, nutationInLongitude:Number, obliquityOfEcliptic:Number ):Number	{
			var LMST:Number = JD2LMST( JD, obsLongitude );
			var correction:Number = nutationInLongitude * Math.cos( obliquityOfEcliptic );
			var LAST:Number = LMST + correction;			
			return LAST;
		}		
	}
}